home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
bbs_util
/
bsrc_260.zip
/
SRC.ZIP
/
MAILOVLY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-20
|
31KB
|
1,385 lines
/*--------------------------------------------------------------------------*/
/* */
/* */
/* ------------ Bit-Bucket Software, Co. */
/* \ 10001101 / Writers and Distributors of */
/* \ 011110 / Freely Available<tm> Software. */
/* \ 1011 / */
/* ------ */
/* */
/* (C) Copyright 1987-96, Bit Bucket Software Co. */
/* */
/* This module was written by Bob Hartman */
/* */
/* BinkleyTerm Mail Control Routines */
/* */
/* */
/* For complete details of the licensing restrictions, please refer */
/* to the License agreement, which is published in its entirety in */
/* the MAKEFILE and BT.C, and also contained in the file LICENSE.260. */
/* */
/* USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE */
/* BINKLEYTERM LICENSING AGREEMENT. IF YOU DO NOT FIND THE TEXT OF */
/* THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO */
/* NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT BIT BUCKET */
/* SOFTWARE CO. AT ONE OF THE ADDRESSES LISTED BELOW. IN NO EVENT */
/* SHOULD YOU PROCEED TO USE THIS FILE WITHOUT HAVING ACCEPTED THE */
/* TERMS OF THE BINKLEYTERM LICENSING AGREEMENT, OR SUCH OTHER */
/* AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO. */
/* */
/* */
/* You can contact Bit Bucket Software Co. at any one of the following */
/* addresses: */
/* */
/* Bit Bucket Software Co. FidoNet 1:104/501, 1:343/491 */
/* P.O. Box 460398 AlterNet 7:42/1491 */
/* Aurora, CO 80046 BBS-Net 86:2030/1 */
/* Internet f491.n343.z1.fidonet.org */
/* */
/* Please feel free to contact us at any time to share your comments about */
/* our software and/or licensing policies. */
/* */
/*--------------------------------------------------------------------------*/
/* Include this file before any other includes or defines! */
#include "includes.h"
static char LOCALFUNC mail_stat (MAILP);
static int LOCALFUNC xmit_install (MAILP, ADDRP);
static MAILP LOCALFUNC xmit_find (MAILP, ADDRP);
static long LOCALFUNC netsize (MAILP);
static int LOCALFUNC any_mail (MAILP);
static void LOCALFUNC do_xmit_line (char *, MAILP);
static void LOCALFUNC xmit_sort (void);
static void LOCALFUNC kill_one (ADDRP address);
static void LOCALFUNC xmit_delete_one (void);
char *mail_status_chars (unsigned int);
static char *HoldFmtStr = "%-12.12s %3d %4.4s %5.5s %c";
static char *HoldNoSize = "%-21.21s %5.5s %c";
void
xmit_sameplace ()
{
MAILP p, p1;
/* Find the guy we just gave mail to */
p = find_mail (&remote_addr);
remote_addr.Zone = remote_addr.Net = remote_addr.Node = remote_addr.Point = 0;
remote_addr.Domain = NULL;
if (p == NULL)
{
/* He is not there */
return;
}
/* Save our current pointer */
p1 = next_mail;
if (p != next_mail)
{
/* If it is not the one we just gave mail to, save ptr and delete */
next_mail = p;
xmit_delete ();
next_mail = p1;
}
else
{
/* It was the guy at the head of the list, so just delete him */
xmit_delete ();
}
/* If we came in with a null, leave with a null */
if (p1 == NULL)
next_mail = NULL;
return;
}
MAILP
find_mail (ADDRP address)
{
MAILP p;
p = mail_top;
while (p != NULL)
{
if ((no_zones || (p->mail_addr.Zone == address->Zone)) &&
(p->mail_addr.Net == address->Net) &&
(p->mail_addr.Node == address->Node) &&
(p->mail_addr.Point == address->Point) &&
((p->mail_addr.Domain == address->Domain) ||
((p->mail_addr.Domain == my_addr.Domain) &&
(address->Domain == NULL))))
break;
p = p->next;
}
return (p);
}
static int LOCALFUNC
xmit_install (MAILP p, ADDRP addr)
{
MAILP p1, p2;
int rettype;
long sztemp;
MDM_TRNS *m; /* MB 93-11-27 */
p2 = find_mail (addr);
if (p2 == NULL)
{
/* We didn't find it in what we have already */
p1 = p;
p1->mail_addr = *addr;
p1->oldest = (unsigned long) time (NULL);
rettype = 0;
}
else
{
/* We found it, so we have to make sure the higher level routine knows */
p1 = p2;
rettype = 1;
}
/*
* Get the size of the entry. If it's a FLO-type file,
* call netsize to find out how big the stuff contained in it
* actually is. If it's a packet, just take its size.
*
* Hold packets don't count.
*/
if (!no_size)
{
sztemp = 0L;
if (!strncmp (&(dta_str.name[10]), "LO", 2))
p1->mailsize += (sztemp = netsize (p1));
else if ((!strncmp (&(dta_str.name[10]), "UT", 2)) ||
(!strncmp (&(dta_str.name[9]), "REQ", 3)))
{
struct tm tmstruc;
time_t curr_time;
p1->numfiles++;
p1->mailsize += (sztemp = dta_str.size);
curr_time = time (NULL);
tmstruc = *localtime (&curr_time); /* Structure assignment */
tmstruc.tm_year = (int) (dta_str.time >> 25) + 80;
tmstruc.tm_mon = (int) ((dta_str.time >> 21) & 0x0f) - 1;
tmstruc.tm_mday = (int) (dta_str.time >> 16) & 0x1f;
tmstruc.tm_hour = (int) (dta_str.time >> 11) & 0x1f;
tmstruc.tm_min = (int) (dta_str.time >> 5) & 0x3f;
tmstruc.tm_sec = (int) dta_str.time & 0x1f;
curr_time = mktime (&tmstruc);
p1->oldest = min ((unsigned long)curr_time, p1->oldest);
}
if (dta_str.name[9] != 'H')
p1->callsize += sztemp;
}
switch (dta_str.name[9])
{
case 'C': /* Crash */
p1->mailtypes |= MAIL_CRASH;
break;
case 'H': /* Hold */
p1->mailtypes |= MAIL_HOLD;
break;
case 'F': /* Normal */
case 'O':
p1->mailtypes |= MAIL_NORMAL;
break;
case 'D': /* Direct */
p1->mailtypes |= MAIL_DIRECT;
break;
case 'R': /* Request */
p1->mailtypes |= MAIL_REQUEST;
break;
}
if (!nodefind (&(p1->mail_addr), 0))
{
p1->mailtypes |= MAIL_UNKNOWN;
return (rettype);
}
/* Don't call for "HOLD" or "REQ" stuff. */
if ((dta_str.name[9] == 'H') || (dta_str.name[9] == 'R'))
{
return (rettype);
}
/* if modem type is undialable, don't call */ /* MB 93-11-27 */
m = mm_head;
while (m != NULL)
{
if (m->mdm == newnodedes.ModemType)
{
if (!(*(m->pre) || *(m->suf)))
return (rettype);
else
break;
}
m = m->next;
}
/* If there's no event, set mail to 'go' */
if (cur_event < 0)
{
p1->mailtypes &= ~MAIL_QSMALL;
p1->mailtypes |= MAIL_WILLGO;
return (rettype);
}
/* If it is a crash only event and we have crashmail, set it to go */
if (e_ptrs[cur_event].behavior & MAT_HIPRICM)
{
if ((dta_str.name[9] == 'C') && (newnodedes.NodeFlags & B_CM))
{
p1->mailtypes &= ~MAIL_QSMALL;
p1->mailtypes |= MAIL_WILLGO;
return (rettype);
}
}
/* If it is a crash only event and this wasn't crash, return */
if ((dta_str.name[9] != 'C') && (e_ptrs[cur_event].behavior & MAT_CM))
{
return (rettype);
}
/* Is this a local only event? */
if (e_ptrs[cur_event].behavior & MAT_LOCAL)
{
/*
* If this is supposed to be only local, then get out if it isn't
*/
if (e_ptrs[cur_event].node_cost >= 0)
{
if ((int) newnodedes.RealCost > e_ptrs[cur_event].node_cost)
{
return (rettype);
}
}
else
{
if ((int) newnodedes.RealCost < -(e_ptrs[cur_event].node_cost))
{
return (rettype);
}
}
}
/* Is this a non-mail window event? */
if ((newnodelist || version7) &&
(!(e_ptrs[cur_event].behavior & MAT_NOMAIL24)))
{
/* If this guy can't handle crash, get out and try again */
if (!(newnodedes.NodeFlags & B_CM))
{
return (rettype);
}
}
/* Is this a receive only event? */
if (e_ptrs[cur_event].behavior & MAT_NOOUT)
{
return (rettype);
}
/* Is this a non-CM event? */
if ((newnodelist || version7) &&
(e_ptrs[cur_event].behavior & MAT_NOCM) &&
(newnodedes.NodeFlags & B_CM))
{
return (rettype);
}
/* See if we spent too much calling him already */
if (bad_call (&(p1->mail_addr), 0))
{
p1->mailtypes |= MAIL_TOOBAD;
return (rettype);
}
/* See if we have enough mail to send */
if (!no_size && e_ptrs[cur_event].mailqsize > p1->callsize)
{
p1->mailtypes |= MAIL_QSMALL;
return (rettype);
}
p1->mailtypes &= ~MAIL_QSMALL;
p1->mailtypes |= MAIL_WILLGO;
return (rettype);
}
static char LOCALFUNC
mail_stat (MAILP p)
{
if (p->mailtypes & MAIL_UNKNOWN)
return ('!');
if (p->mailtypes & MAIL_TOOBAD)
return ('x');
if (p->mailtypes & MAIL_TRIED)
return ('#');
if (p->mailtypes & MAIL_WILLGO)
return ('*');
if (p->mailtypes & MAIL_QSMALL)
return ('<');
return ('-');
}
char msc[10];
char *
mail_status_chars (unsigned int p)
{
char *q;
q = msc;
if (p & MAIL_CRASH)
*q++ = 'C';
if (p & MAIL_HOLD)
*q++ = 'H';
if (p & MAIL_DIRECT)
*q++ = 'D';
if (p & MAIL_NORMAL)
*q++ = 'N';
if (p & MAIL_REQUEST)
*q++ = 'R';
*q++ = '\0';
return (msc);
}
void
xmit_window (MAILP p1)
{
MAILP p;
short i;
char j1[32];
char *jPtr;
if (!fullscreen)
return;
p = p1;
sb_fillc (holdwin, ' ');
jPtr = j1;
if (p == NULL)
{
sb_move (holdwin, 3, 5);
sb_puts (holdwin, MSG_TXT (M_NOTHING_IN_OUTBOUND));
return;
}
strcpy (j1, MSG_TXT (M_OUTBOUND_HEADER));
sb_move (holdwin, 1, 2);
sb_puts (holdwin, jPtr);
for (i = 2; i < SB_ROW_HOLD; i++)
{
if (p == NULL)
break;
do_xmit_line (j1, p);
sb_move (holdwin, i, 2);
sb_puts (holdwin, jPtr);
p = p->next;
}
sb_show ();
}
static void LOCALFUNC
do_xmit_line (char *line, MAILP p)
{
ADDR addrT;
if (no_size)
{
(void) sprintf (line, HoldNoSize,
Full_Addr_Str (&(p->mail_addr)),
mail_status_chars (p->mailtypes),
mail_stat (p));
}
else
{
addrT = p->mail_addr;
addrT.Domain = NULL;
(void) sprintf (line, HoldFmtStr,
Full_Addr_Str (&addrT),
(p->numfiles > 999 ? 999 : p->numfiles),
numdisp (p->mailsize),
mail_status_chars (p->mailtypes),
mail_stat (p));
}
}
static void LOCALFUNC
xmit_sort ()
{
MAILP p, p1, p2;
p = mail_top;
/* Find the first that is sendable */
while (p != NULL)
{
if ((p->mailtypes & MAIL_WILLGO) &&
(!(p->mailtypes & MAIL_TOOBAD)) &&
(!(p->mailtypes & MAIL_UNKNOWN)))
break;
p = p->next;
}
if (p == NULL)
return;
/* Put the first sendable one on top */
if (p != mail_top)
{
p->prev->next = p->next;
if (p->next != NULL)
p->next->prev = p->prev;
p->prev = NULL;
p->next = mail_top;
mail_top->prev = p;
mail_top = p;
}
p1 = p;
p = p1->next;
while (p != NULL)
{
if ((p->mailtypes & MAIL_WILLGO) &&
(!(p->mailtypes & MAIL_TOOBAD)) &&
(!(p->mailtypes & MAIL_UNKNOWN)))
{
if (p->prev == p1)
{
p1 = p;
p = p->next;
continue;
}
p2 = p->next;
p->prev->next = p->next;
if (p->next != NULL)
p->next->prev = p->prev;
p->next = p1->next;
if (p1->next != NULL)
p1->next->prev = p;
p->prev = p1;
p1->next = p;
p1 = p;
p = p2;
}
else
{
p = p->next;
}
}
}
void
xmit_reset (int display)
{
MAILP p;
int j, k, zone;
char *q, *s;
char *domain;
char *HoldName;
char pointspec[128];
ADDR tmp;
struct FILEINFO zone_dir =
{0};
struct FILEINFO pnt_dir =
{0};
long longzone;
/* First get rid of all the old junk */
p = mail_top;
if (p != NULL)
{
while (p->next != NULL)
p = p->next;
while (p->prev != NULL)
{
p = p->prev;
free (p->next);
}
if (p != NULL)
free (p);
}
p = mail_top = NULL;
/*
* Initialize domain to scan. Choose (of course) the
* domain of our primary address.
*
* This domain is special in that its outbound is hold_area.
* All the other domains use their abbreviation as the name
* of their outbounds.
*/
k = 0;
domain = domain_name[0];
(void) strcpy (pointspec, hold_area);
q = &(pointspec[strlen (pointspec)]) - 1;
do
{
/*
* Initialize scan of zones in this domain. Using findfirst/findnext,
* get all the matching directories.
*/
(void) strcpy (q, ".*");
j = 0;
while (!dfind (&zone_dir, pointspec, j))
{
j = 1; /* Flip findfirst/findnext to findnext */
/*
* We have a match on the outbound spec. Make sure it's a directory.
*
* Then:
*
* 1) If no extension, we may only use it if this is alias 0
* 2) If an extension, it must be a 3-digit hex number
*
* If the extension passes one of these tests, get to work!
*/
if (!(zone_dir.attr & FA_SUBDIR))
continue;
q = strchr (zone_dir.name, '.');
if (q == NULL)
{
if (k != 0 && !no_zones)
continue;
zone = (int) alias[0].Zone;
}
else
{
if (no_zones)
continue;
s = ++q;
longzone = strtol (q, &q, 16);
if ((s + 3) != q)
continue;
zone = (int) longzone;
/*
* To avoid duplicating the primary scan,
* make sure that this isn't "domainname[0].zone[0]".
*/
if (!k && zone == (int) alias[0].Zone)
continue;
}
/*
* OK. We have a domain, an outbound directory, and a zone.
* That means there's an outbound to scan.
*
* Start by scanning the nodes.
*/
tmp.Zone = zone;
tmp.Domain = domain;
tmp.Net = tmp.Node = tmp.Point = 0;
p = xmit_find (p, &tmp);
/*
* Now we do the points contained in this outbound.
*
*/
if (pvtnet <= 0)
{
int f = 0;
HoldName = HoldAreaNameMunge (&tmp);
(void) sprintf (pointspec, "%s*.PNT", HoldName);
while (!dfind (&pnt_dir, pointspec, f))
{
f = 1;
if (sscanf (pnt_dir.name, "%04hx%04hx.", &(tmp.Net), &(tmp.Node)) != 2)
continue;
tmp.Point = 1;
p = xmit_find (p, &tmp);
} /* got one */
if (f)
(void) dfind (&pnt_dir, NULL, 2);
}
} /* while !dfind (...) to get outbounds */
if (j)
(void) dfind (&zone_dir, NULL, 2);
/*
* See if there are any more domains. If so, set up the right name
* for the outbound, so we can find 'em.
*/
if ((domain = domain_name[++k]) != NULL)
{
*domain_loc = '\0';
(void) strcpy (pointspec, domain_area);
q = &(pointspec[strlen (pointspec)]);
s = domain_abbrev[k];
if (s != NULL)
while (*s)
*q++ = *s++;
}
}
while (domain != NULL);
next_mail = NULL;
xmit_sort ();
if (display)
xmit_window (mail_top);
next_rescan = (long) time (NULL) + 600L; /* At least 10 min to next scan */
}
static MAILP LOCALFUNC
xmit_find (MAILP p, ADDRP address)
{
int j;
char next_one[127];
char *HoldName;
ADDR tmp;
tmp = *address;
HoldName = HoldAreaNameMunge (address);
if (address->Point != 0)
{
(void) sprintf (next_one, "%s%04hx%04hx.PNT\\*.*",
HoldName, address->Net, address->Node);
tmp.Point = 0;
}
else
{
(void) sprintf (next_one, "%s*.*", HoldName);
tmp.Net = 0;
tmp.Node = 0;
tmp.Point = 0;
}
j = 0;
while (!dfind (&dta_str, next_one, j))
{
j = 1;
/* We have a match. Was it a .FLO file or a .OUT file? */
if (strncmp (&(dta_str.name[10]), "LO", 2) == 0)
{
/* FLO, DLO, CLO and HLO are the only ones! */
if (strchr ("FDCH", dta_str.name[9]) == NULL)
continue;
}
else if (strncmp (&(dta_str.name[10]), "UT", 2) == 0)
{
/* OUT, DUT, CUT and HUT are the only ones! */
if (strchr ("ODCH", dta_str.name[9]) == NULL)
continue;
}
else if (strncmp (&(dta_str.name[9]), "REQ", 3) != 0)
continue;
/* We found a name, remember it */
if (address->Point != 0)
{
if (sscanf (dta_str.name, "%08hx.", &(tmp.Point)) != 1)
continue;
}
else if (sscanf (dta_str.name, "%04hx%04hx.", &(tmp.Net), &(tmp.Node)) != 2)
continue;
if (p == NULL)
{
p = mail_top = (MAILP) calloc (sizeof (MAIL), 1);
}
else
{
p->next = (MAILP) calloc (sizeof (MAIL), 1);
p->next->prev = p;
p = p->next;
}
if (xmit_install (p, &tmp))
{
/* No good */
if (p->prev != NULL)
{
p = p->prev;
free (p->next);
p->next = NULL;
}
else
{
free (p);
p = mail_top = NULL;
}
}
} /* while (!done) */
if (j)
(void) dfind (&dta_str, NULL, 2);
return (p);
}
int
xmit_next (ADDRP xaddr)
{
int i, j;
for (i = 0; i < 2; i++)
{
/* Set up the proper pointer */
if ((next_mail == NULL) || (next_mail->next == NULL))
{
if (next_rescan < (long) time (NULL))
xmit_reset (1);
next_mail = mail_top;
}
else
{
next_mail = next_mail->next;
}
/* Loop through till we find something we can send */
while (next_mail != NULL)
{
if ((next_mail->mailtypes & MAIL_WILLGO) &&
(!(next_mail->mailtypes & MAIL_UNKNOWN)) &&
(!(next_mail->mailtypes & MAIL_TOOBAD)))
{
if (bad_call (&(next_mail->mail_addr), 0))
{
next_mail->mailtypes |= MAIL_TOOBAD;
}
else
{
/* If multitasking, check for mail before calling */
if ((TaskNumber != 0) && ((j = any_mail (next_mail)) <= 0))
{
if (j == 0)
xmit_delete ();
else
next_mail = next_mail->next;
continue;
}
*xaddr = next_mail->mail_addr;
xmit_window (next_mail);
return (1);
}
}
next_mail = next_mail->next;
}
}
/* Oh well, we tried */
xmit_window (mail_top);
return (0);
}
static void LOCALFUNC
xmit_delete_one ()
{
MAILP p;
if (any_mail (next_mail) != 0)
{
status_line (MSG_TXT (M_STILL_HAVE_MAIL), Full_Addr_Str (&(next_mail->mail_addr)));
/* We still have something for him */
next_mail->mailtypes &= ~MAIL_WILLGO;
next_mail->mailtypes |= MAIL_TRIED;
return;
}
if (next_mail != mail_top)
{
p = next_mail->next;
next_mail = next_mail->prev;
free (next_mail->next);
next_mail->next = p;
if (p != NULL)
p->prev = next_mail;
}
else
{
mail_top = mail_top->next;
free (next_mail);
if (mail_top != NULL)
mail_top->prev = NULL;
next_mail = NULL;
}
}
void
xmit_delete ()
{
int i;
if (next_mail == NULL && no_EMSI_Session)
return;
if (no_EMSI_Session)
{
xmit_delete_one ();
}
else
{
for (i = (num_rakas - 1); i >= 0; i--)
{
next_mail = find_mail (&remote_akas[i]);
if (next_mail != NULL)
xmit_delete_one ();
}
}
xmit_window (mail_top);
no_EMSI_Session = TRUE;
num_rakas = 0;
}
int
bad_call (ADDRP baddr, int rwd)
{
int res;
int i, j;
struct FILEINFO bad_dta = {0};
FILE *bad_wazoo;
char *p;
char *HoldName;
char fname[128];
char fname1[128];
HoldName = HoldAreaNameMunge (baddr);
(void) sprintf (fname, "%s%s.$$?", HoldName, Hex_Addr_Str (baddr));
j = (int) strlen (fname) - 1; /* Point at ? */
res = -1; /* Initialize to fail */
i = 0; /* This says findfirst */
while (!dfind (&bad_dta, fname, i)) /* as long as we match */
{
if (isdigit (bad_dta.name[11])) /* is there a digit? */
{
fname[j] = bad_dta.name[11]; /* Yes, copy to fname */
res = fname[j] - '0'; /* Save it for testing */
break; /* Get out of while */
}
else
i = 1; /* Else use findnext */
}
if (i)
(void) dfind (&bad_dta, NULL, 2);
if (res == -1) /* Successful search? */
{
fname[j] = '0'; /* No, base digit = 0 */
}
if (rwd > 0)
{
/* Writing a bad call */
/* First create a filename that is one higher than what we've got */
(void) strcpy (fname1, fname);
fname1[j]++;
if (fname1[j] > '9')
fname1[j] = '9';
if (res == -1) /* Did we have a file? */
{ /* No, make one. */
if (rwd == 2) /* No carrier */
res = open (fname, O_CREAT | O_WRONLY | O_BINARY, S_IREAD | S_IWRITE);
else /* With carrier */
res = open (fname1, O_CREAT | O_WRONLY | O_BINARY, S_IREAD | S_IWRITE);
i = rwd - 1; /* zero-based count */
(void) write (res, (char *) &i, sizeof (int));
(void) close (res); /* close the file */
}
else
{ /* There was a file */
/*
* 2 = Unsuccessful, No carrier. Update contents of the file.
*/
if (rwd == 2)
{
i = open (fname, O_RDONLY | O_BINARY);
(void) read (i, (char *) &res, sizeof (int));
(void) close (i);
++res;
i = open (fname, O_CREAT | O_WRONLY | O_BINARY, S_IREAD | S_IWRITE);
(void) write (i, (char *) &res, sizeof (int));
(void) close (i);
}
/*
* 1 = Unsuccessful, Carrier. Update file name to reflect the
* failure.
*/
else
(void) rename (fname, fname1);
}
}
else if (rwd == 0)
{
/*
* 0 = We are reading a bad call status
*/
/* Is it automatically ok (no .$$ file there) ? */
if (res == -1)
return (0);
/* Were there too many connects with carrier? */
if (res >= max_connects)
return (1);
/* Ok, check for connects without carrier */
res = 0;
i = open (fname, O_RDONLY | O_BINARY);
(void) read (i, (char *) &res, sizeof (int));
(void) close (i);
return (res >= max_noconnects);
}
else
{
/*
* -1 = Cleanup of bad call status. This happens in two steps:
* a) delete 'netnode.$$?' in hold area;
* b) if a 'netnode.Z' file exists in hold area,
* 1) delete all BADWAZOO.xxx files listed in the .Z file;
* 2) delete the 'netnode.z' file.
*/
if (res != -1)
(void) unlink (fname);
if (!mail_finished)
return (0);
(void) sprintf (fname, "%s%s.Z", HoldName, Hex_Addr_Str (baddr));
if (dexists (fname))
{
if ((bad_wazoo = fopen (fname, read_ascii)) == NULL)
(void) got_error (MSG_TXT (M_OPEN_MSG), fname);
else
{
while (!feof (bad_wazoo))
{
e_input[0] = '\0';
if (!fgets (e_input, 64, bad_wazoo))
break;
/* Point to BADWAZOO.xxx */
p = strchr (e_input, ' ') + 1;
/* Then just past it and terminate */
p = strchr (p, ' ');
*p = '\0';
/* Back to where we were */
p = strchr (e_input, ' ') + 1;
/* Build file name and delete file */
(void) strcpy (fname1, CURRENT.sc_Inbound);
(void) strcat (fname1, p);
(void) unlink (fname1);
}
(void) fclose (bad_wazoo);
}
(void) unlink (fname);
}
}
return (0);
}
void
set_up_outbound ()
{
MAILP mp;
xmit_reset (1);
/* and remember where we left off */
if (hist.next_addr.Net != 0)
{
next_addr = hist.next_addr;
next_addr.Domain = NULL;
mp = find_mail (&next_addr);
if ((mp == NULL) || (mp->prev == NULL))
{
next_mail = NULL;
xmit_window (mail_top);
}
else
{
next_mail = mp->prev;
xmit_window (next_mail);
}
}
else
{
next_addr.Zone = 0;
next_addr.Net = 0;
next_addr.Node = 0;
next_addr.Point = 0;
next_addr.Domain = NULL;
xmit_window (mail_top);
}
}
void
kill_bad (void)
{
int j, k, zone;
char *q, *s;
char *domain;
char *HoldName;
char pointspec[255];
ADDR tmp;
struct FILEINFO zone_dir = {0};
struct FILEINFO pnt_dir = {0};
long longzone;
/*
* Initialize domain to scan. Choose (of course) the
* domain of our primary address.
*
* This domain is special in that its outbound is hold_area.
* All the other domains use their abbreviation as the name
* of their outbounds.
*/
k = 0;
domain = domain_name[0];
(void) strcpy (pointspec, hold_area);
q = &(pointspec[strlen (pointspec)]) - 1;
do
{
/*
* Initialize scan of zones in this domain. Using findfirst/findnext,
* get all the matching directories.
*/
(void) strcpy (q, ".*");
j = 0;
while (!dfind (&zone_dir, pointspec, j))
{
j = 1; /* Flip findfirst/findnext to findnext */
/*
* We have a match on the outbound spec. Make sure it's a directory.
*
* Then:
*
* 1) If no extension, we may only use it if this is alias 0
* 2) If an extension, it must be a 3-digit hex number
*
* If the extension passes one of these tests, get to work!
*/
if (!(zone_dir.attr & FA_SUBDIR))
continue;
q = strchr (zone_dir.name, '.');
if (q == NULL)
{
if (k != 0 && !no_zones)
continue;
zone = (int) alias[0].Zone;
}
else
{
if (no_zones)
continue;
s = ++q;
longzone = strtol (q, &q, 16);
if ((s + 3) != q)
continue;
zone = (int) longzone;
/*
* To avoid duplicating the primary scan,
* make sure that this isn't "domainname[0].zone[0]".
*/
if (!k && zone == (int) alias[0].Zone)
continue;
}
/*
* OK. We have a domain, an outbound directory, and a zone.
* That means there's an outbound to scan.
*
* Start by scanning the nodes.
*/
tmp.Zone = zone;
tmp.Domain = domain;
tmp.Net = tmp.Node = tmp.Point = 0;
kill_one (&tmp);
/*
* Now we do the points contained in this outbound.
*
*/
if (pvtnet <= 0)
{
int f = 0;
HoldName = HoldAreaNameMunge (&tmp);
(void) sprintf (pointspec, "%s*.PNT", HoldName);
while (!dfind (&pnt_dir, pointspec, f))
{
f = 1;
if (sscanf (pnt_dir.name, "%04hx%04hx.", &(tmp.Net), &(tmp.Node)) != 2)
continue;
tmp.Point = 1;
kill_one (&tmp);
} /* got one */
if (f)
(void) dfind (&pnt_dir, NULL, 2);
}
} /* while !dfind (...) to get outbounds */
if (j)
(void) dfind (&zone_dir, NULL, 2);
/*
* See if there are any more domains. If so, set up the right name
* for the outbound, so we can find 'em.
*/
if ((domain = domain_name[++k]) != NULL)
{
*domain_loc = '\0';
(void) strcpy (pointspec, domain_area);
q = &(pointspec[strlen (pointspec)]);
s = domain_abbrev[k];
if (s != NULL)
while (*s)
*q++ = *s++;
}
}
while (domain != NULL);
}
static void LOCALFUNC
kill_one (ADDRP address)
{
int j;
char next_one[255];
char thisfile[255];
char *HoldName;
char *p;
HoldName = HoldAreaNameMunge (address);
if (address->Point != 0)
{
(void) sprintf (next_one, "%s%04hx%04hx.PNT\\*.$$?",
HoldName, address->Net, address->Node);
}
else
{
(void) sprintf (next_one, "%s*.$$?", HoldName);
}
j = 0;
strcpy (thisfile, next_one);
p = strrchr (thisfile, '*');
while (!dfind (&dta_str, next_one, j))
{
j = 1;
strcpy (p, dta_str.name);
status_line (">Deleting %s", thisfile);
unlink (thisfile);
} /* while (!done) */
if (j)
(void) dfind (&dta_str, NULL, 2);
}
/*
* Calculate size of mail queued for outbound.
* Used to determine whether or not we have enough
* mail to merit an outbound call.
*
* The original version of this code was donated by Henry Clark.
*/
static long LOCALFUNC
netsize (MAILP p)
{
struct stat stbuf;
char net_path[127];
char *ptr;
FILE *temp;
long accum = 0L;
char *q;
/* Append the ARCmail file name to the path line */
(void) sprintf (net_path, "%s%s.%s",
HoldAreaNameMunge (&(p->mail_addr)),
Hex_Addr_Str (&(p->mail_addr)),
&dta_str.name[9]);
temp = share_fopen (net_path, read_binary, DENY_NONE);
if (temp == (FILE *) NULL)
return (accum);
while (!feof (temp))
{
/*
* Make sure of a nice zero there if we're at an undetected EOF.
* Then try to read a line from the file.
*/
net_path[0] = '\0';
(void) fgets (net_path, 79, temp);
/*
* Clean up anything we don't want to see (blanks, tabs, CR, etc)
*/
for (q = ptr = net_path; *q; q++)
if (*q <= ' ')
*q = '\0';
/*
* File disposition commands should be skipped over to get to
* actual filenames.
*/
if ((*ptr == TRUNC_AFTER) ||
(*ptr == DELETE_AFTER) ||
(*ptr == SHOW_DELETE_AFTER) ||
(*ptr == NOTHING_AFTER))
ptr++;
/*
* Now -- if what's left starts with a semicolon, it's a comment.
* If it starts with a tilde, the file has already been sent. If
* what we see is a zero, there's nothing on the line. In any one
* of these cases, we should skip this line.
*/
if ((*ptr == '\0') ||
(*ptr == ';') ||
(*ptr == '~'))
continue;
/*
* Get the file size by doing a stat call. If it's not there
* then we obviously need not add any size in. If the file is
* arcmail, figure it into the "oldest" calculation.
*/
if (stat (ptr, &stbuf)) /* file exist? */
continue;
else
{
p->numfiles++;
accum += stbuf.st_size;
if (is_arcmail (ptr, 1 - strlen (ptr)))
p->oldest = min ((unsigned long)stbuf.st_ctime, p->oldest);
}
}
(void) fclose (temp);
return (accum);
}
/*
* Figure out if there's any mail for the specified node.
* Used to determine if we need to actually make a call.
*
* Returns 0 for no mail at all
* 1 for non-hold mail
* -1 for hold mail only
*
* I can't remember who was the first to demand this. I've been
* pummelled for a while and there's almost certainly been a loss
* of grey matter.
*/
static int LOCALFUNC
any_mail (MAILP node)
{
struct FILEINFO dta = {0};
char next_one[127];
int ret = 0;
int j = 0;
(void) sprintf (next_one, "%s%s.*",
HoldAreaNameMunge (&(node->mail_addr)),
Hex_Addr_Str (&(node->mail_addr)));
while (!dfind (&dta, next_one, j))
{
j = 1;
#ifndef JACK_DECKER
if (dta.name[9] == 'H')
{
ret = -1;
continue;
}
#endif
if ((!strncmp (&(dta.name[10]), "LO", 2)) ||
(!strncmp (&(dta.name[10]), "UT", 2)))
{
ret = 1;
break;
}
}
if (j)
(void) dfind (&dta, NULL, 2);
return (ret);
}